import random
import string
from io import BytesIO

from PIL import Image, ImageDraw, ImageFont, ImageFilter


# 生成随机字符串
def generate_random_code(length: int = 4) -> str:
    """生成指定长度的随机验证码字符串"""
    # 包含大小写字母和数字
    characters = string.ascii_letters + string.digits
    return ''.join(random.choice(characters) for _ in range(length))

# 生成随机数字字符串
def generate_random_sms_code(length: int = 4) -> str:
    """生成指定长度的随机验证码字符串"""
    # 数字
    characters =string.digits
    return ''.join(random.choice(characters) for _ in range(length))

# 生成验证码图片
def generate_captcha_image(code: str = None, width: int = 120, height: int = 40) -> tuple:
    """
    生成验证码图片
    
    参数:
        code: 验证码字符串，如果为None则自动生成
        width: 图片宽度
        height: 图片高度
        
    返回:
        验证码图片的BytesIO对象和验证码字符串
    """
    if not code:
        code = generate_random_code()
    
    # 创建图片对象，背景色为白色
    image = Image.new('RGB', (width, height), (255, 255, 255))
    
    # 尝试加载系统字体，如果失败则使用默认字体
    try:
        # 可以根据系统情况更换合适的字体路径
        font = ImageFont.truetype('arial.ttf', 30)
    except:
        font = ImageFont.load_default(30)
    
    # 创建画笔对象
    draw = ImageDraw.Draw(image)
    
    # 绘制干扰点
    for _ in range(100):
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw.point((x, y), fill=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
    
    # 绘制干扰线
    for _ in range(5):
        x1 = random.randint(0, width)
        y1 = random.randint(0, height)
        x2 = random.randint(0, width)
        y2 = random.randint(0, height)
        draw.line((x1, y1, x2, y2), fill=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)), width=1)
    
    # 绘制验证码文字，每个字符使用不同颜色和位置
    for i, char in enumerate(code):
        x = 10 + i * 25
        y = random.randint(5, 10)
        draw.text(
            (x, y), 
            char, 
            font=font, 
            fill=(random.randint(30, 100), random.randint(30, 100), random.randint(30, 100))
        )
    
    # 轻微模糊处理
    image = image.filter(ImageFilter.GaussianBlur(radius=0.5))
    
    # 将图片保存到BytesIO对象
    buf = BytesIO()
    image.save(buf, 'png')
    buf.seek(0)
    
    return buf, code
    